﻿using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using collision_and_rigid;
using game_config;

namespace game_stuff
{   [Serializable]
    public class PlayBuffFixEffectSave
    {
        public readonly PlayBuffFixEffect playBuffFixEffect;
        public readonly uint lv;

        public PlayBuffFixEffectSave(PlayBuffFixEffect playBuffFixEffect, uint lv)
        {
            this.playBuffFixEffect = playBuffFixEffect;
            this.lv = lv;
        }
    }


    [Serializable]
    public class CharacterInitData
    {
        public int Gid { get; }
        public int TeamId { get; }
        private weapon_id[] Weapons { get; }
        private size BodySize { get; }
        private int BaseAttrId { get; }

        private float SurviveBaseLack { get; }
        private Dictionary<passive_id, uint>? InitPassiveTraits { get; }

        private PlayBuffFixEffectSave[] PlayBuffFixEffects { get; }

        private GameItem[]? InitItems { get; }
        private int WeaponMaxNum { get; }

        public static CharacterInitData GenNpcByConfig(int gid, int teamId, IEnumerable<weapon_id> weapons, size size,
            int baseAttrId, int battleNpcMaxWeaponSlot)
        {
            var weaponIds = weapons.ToArray();
            // var dictionary = new Dictionary<int, weapon_id>();
            // for (var i = 0; i < weapons.Length; i++)
            // {
            //     dictionary[i] = Weapon.GenId(weapons[i]);
            // }


            return new CharacterInitData(gid, teamId, weaponIds, size, baseAttrId, 0, battleNpcMaxWeaponSlot,
                new Dictionary<passive_id, uint>(), null, Array.Empty<PlayBuffFixEffectSave>());
        }

        public static CharacterInitData GenPlayerByConfig(int gid, int teamId, weapon_id[] weapons, size size,
            int baseAttrId, PlayBuffFixEffectSave[] effectSaves,
            float surviveBaseLack = 0,
            Dictionary<passive_id, uint>? initPassive = null, GameItem[]? gameItems = null
        )
        {
            var min = MathTools.Min(CommonConfig.OtherConfig!.weapon_num, weapons.Length);
            var weaponIds = weapons.Take(min).ToArray();


            return new CharacterInitData(gid, teamId, weaponIds, size, baseAttrId, surviveBaseLack,
                CommonConfig.OtherConfig.weapon_num,
                initPassive, gameItems, effectSaves);
            // var d2 = new Dictionary<passive_id, PassiveTrait>();
        }

        private CharacterInitData(int gid, int teamId, weapon_id[] weapons, size bodySize,
            int baseAttrId, float surviveBaseLack, int weaponMaxNum, Dictionary<passive_id, uint>? initPassiveTraits,
            GameItem[]? initItems, PlayBuffFixEffectSave[] playBuffFixEffects)
        {
            Gid = gid;
            TeamId = teamId;
            Weapons = weapons;
            BodySize = bodySize;
            BaseAttrId = baseAttrId;
            WeaponMaxNum = weaponMaxNum;
            InitPassiveTraits = initPassiveTraits;
            InitItems = initItems;
            SurviveBaseLack = surviveBaseLack;
            PlayBuffFixEffects = playBuffFixEffects;
        }


        public CharacterBody GenCharacterBody(TwoDPoint startPos,
            Dictionary<passive_id, PassiveTrait>? passiveTraits = null, PlayingItemBag? playingItemBag = null)
        {
            var dd = passiveTraits ?? new Dictionary<passive_id, PassiveTrait>();
            if (InitPassiveTraits != null)
            {
                foreach (var passiveTrait in InitPassiveTraits
                             .Select(keyValuePair => PassiveTrait.GenManyByPId(keyValuePair.Key, keyValuePair.Value))
                             .SelectMany(genManyByPId => genManyByPId))
                {
                    if (dd.TryGetValue(passiveTrait.PassId, out var nowPass))
                    {
                        nowPass.AddLevel(passiveTrait.Level);
                    }
                    else
                    {
                        dd[passiveTrait.PassId] = passiveTrait;
                    }
                }
            }


#if DEBUG
            Console.Out.WriteLine($"pass d to create : {dd.Count}");
#endif
            var genBaseAttrById = GameTools.GenBaseAttrById(BaseAttrId);
            if (SurviveBaseLack > 0)
            {
                genBaseAttrById.BaseAttributeSurviveFix(SurviveBaseLack);
            }

            var characterStatus = new CharacterStatus(Gid, genBaseAttrById, playingItemBag ??
                                                                            PlayingItemBag.InitByConfig(), dd,
                WeaponMaxNum);


            var characterBody = new CharacterBody(startPos, BodySize, characterStatus, startPos,
                AngleSight.StandardAngleSight(),
                TeamId);

            if (PlayBuffFixEffects.Any())
            {
                foreach (var playBuffFixEffectSave in PlayBuffFixEffects)
                {
                    characterStatus.PickABuffFixEffect(playBuffFixEffectSave.playBuffFixEffect,
                        playBuffFixEffectSave.lv);
                }
            }

            if (InitItems != null)
            {
                var immutableArray = InitItems.ToImmutableList();
                characterStatus.PickGameItems(immutableArray);
            }

            foreach (var weapon in Weapons.Select(Weapon.GenById))
            {
// #if DEBUG
//                 Console.Out.WriteLine($"{weapon.LogUserString()}");
// #endif
                weapon.PickedBySomebody(characterStatus);
#if DEBUG
                Console.Out.WriteLine($"got weapon broadcast :{weapon.LogUserString()}");
#endif
            }


            return characterBody;
        }
    }
}